# app/management/commands/start_scheduler.py
import signal
import sys
import time
import logging
from django.core.management.base import BaseCommand
from django.conf import settings

from utils.scheduler_manager import SchedulerManager

logger = logging.getLogger(__name__)


class Command(BaseCommand):
    help = '启动任务调度器'
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.scheduler_manager = None
        self.running = False
    
    def add_arguments(self, parser):
        parser.add_argument(
            '--daemon',
            action='store_true',
            help='以守护进程模式运行',
        )
        parser.add_argument(
            '--check-interval',
            type=int,
            default=5,
            help='状态检查间隔（秒），默认5秒',
        )
    
    def handle(self, *args, **options):
        self.stdout.write(
            self.style.SUCCESS('正在启动任务调度器...')
        )
        
        # 设置信号处理器
        signal.signal(signal.SIGTERM, self._signal_handler)
        signal.signal(signal.SIGINT, self._signal_handler)
        
        try:
            # 初始化调度器管理器
            self.scheduler_manager = SchedulerManager()
            
            # 启动调度器
            self.scheduler_manager.start_scheduler()
            
            self.stdout.write(
                self.style.SUCCESS('✅ 任务调度器启动成功')
            )
            
            # 显示调度器状态
            self._show_scheduler_status()
            
            self.running = True
            
            if options['daemon']:
                self._run_daemon_mode(options['check_interval'])
            else:
                self._run_interactive_mode(options['check_interval'])
                
        except KeyboardInterrupt:
            self.stdout.write(
                self.style.WARNING('\n收到中断信号，正在关闭调度器...')
            )
        except Exception as e:
            self.stdout.write(
                self.style.ERROR(f'启动调度器失败: {e}')
            )
            logger.error(f"启动调度器失败: {e}", exc_info=True)
            sys.exit(1)
        finally:
            self._shutdown()
    
    def _signal_handler(self, signum, frame):
        """信号处理器"""
        self.stdout.write(
            self.style.WARNING(f'\n收到信号 {signum}，正在关闭调度器...')
        )
        self.running = False
    
    def _run_daemon_mode(self, check_interval):
        """守护进程模式"""
        self.stdout.write(
            self.style.SUCCESS('以守护进程模式运行，使用 Ctrl+C 或发送 SIGTERM 信号停止')
        )
        
        while self.running:
            try:
                time.sleep(check_interval)
                
                # 检查调度器状态
                if not self.scheduler_manager.is_running:
                    self.stdout.write(
                        self.style.ERROR('⚠️  检测到调度器异常停止，尝试重启...')
                    )
                    try:
                        self.scheduler_manager.start_scheduler()
                        self.stdout.write(
                            self.style.SUCCESS('✅ 调度器重启成功')
                        )
                    except Exception as e:
                        self.stdout.write(
                            self.style.ERROR(f'❌ 调度器重启失败: {e}')
                        )
                        logger.error(f"调度器重启失败: {e}", exc_info=True)
                        break
                        
            except KeyboardInterrupt:
                break
            except Exception as e:
                logger.error(f"守护进程运行错误: {e}", exc_info=True)
                time.sleep(check_interval)
    
    def _run_interactive_mode(self, check_interval):
        """交互模式"""
        self.stdout.write(
            self.style.SUCCESS('交互模式运行中，可用命令:')
        )
        self.stdout.write('  status  - 显示调度器状态')
        self.stdout.write('  jobs    - 显示所有任务')
        self.stdout.write('  quit    - 退出程序')
        self.stdout.write('  help    - 显示帮助')
        self.stdout.write('使用 Ctrl+C 退出')
        self.stdout.write('-' * 50)
        
        last_status_time = 0
        
        while self.running:
            try:
                # 定期显示状态
                current_time = time.time()
                if current_time - last_status_time > check_interval:
                    self._show_brief_status()
                    last_status_time = current_time
                
                # 检查用户输入（非阻塞）
                if sys.stdin in select.select([sys.stdin], [], [], 0.1)[0]:
                    command = input().strip().lower()
                    self._handle_command(command)
                
                time.sleep(0.1)
                
            except KeyboardInterrupt:
                break
            except Exception as e:
                logger.error(f"交互模式运行错误: {e}", exc_info=True)
                time.sleep(1)
    
    def _handle_command(self, command):
        """处理用户命令"""
        if command == 'status':
            self._show_scheduler_status()
        elif command == 'jobs':
            self._show_jobs()
        elif command in ['quit', 'exit', 'q']:
            self.running = False
        elif command == 'help':
            self._show_help()
        elif command:
            self.stdout.write(
                self.style.WARNING(f'未知命令: {command}，输入 help 查看帮助')
            )
    
    def _show_help(self):
        """显示帮助信息"""
        self.stdout.write('可用命令:')
        self.stdout.write('  status  - 显示详细调度器状态')
        self.stdout.write('  jobs    - 显示所有任务列表')
        self.stdout.write('  quit    - 退出程序')
        self.stdout.write('  help    - 显示此帮助信息')
    
    def _show_scheduler_status(self):
        """显示调度器详细状态"""
        if not self.scheduler_manager:
            return
        
        status = self.scheduler_manager.get_scheduler_status()
        
        self.stdout.write('\n' + '=' * 50)
        self.stdout.write('📊 调度器状态信息')
        self.stdout.write('=' * 50)
        
        # 运行状态
        if status['running']:
            self.stdout.write(
                f"状态: {self.style.SUCCESS('✅ 运行中')}"
            )
        else:
            self.stdout.write(
                f"状态: {self.style.ERROR('❌ 已停止')}"
            )
        
        # 任务数量
        self.stdout.write(f"任务数量: {status['job_count']}")
        
        # 下次运行时间
        if status['next_run_time']:
            self.stdout.write(f"下次运行: {status['next_run_time']}")
        else:
            self.stdout.write("下次运行: 无")
        
        self.stdout.write('=' * 50 + '\n')
    
    def _show_brief_status(self):
        """显示简要状态"""
        if not self.scheduler_manager:
            return
        
        status = self.scheduler_manager.get_scheduler_status()
        status_text = "运行中" if status['running'] else "已停止"
        self.stdout.write(
            f"[{time.strftime('%H:%M:%S')}] "
            f"状态: {status_text}, "
            f"任务数: {status['job_count']}"
        )
    
    def _show_jobs(self):
        """显示所有任务"""
        if not self.scheduler_manager:
            return
        
        jobs = self.scheduler_manager.get_jobs()
        
        self.stdout.write('\n' + '=' * 80)
        self.stdout.write('📋 任务列表')
        self.stdout.write('=' * 80)
        
        if not jobs:
            self.stdout.write('暂无任务')
        else:
            self.stdout.write(
                f"{'ID':<20} {'名称':<20} {'下次运行':<20} {'状态':<10}"
            )
            self.stdout.write('-' * 80)
            
            for job in jobs:
                status = "运行中" if not job['pending'] else "等待中"
                next_run = job['next_run_time'].strftime('%m-%d %H:%M:%S') if job['next_run_time'] else '无'
                
                self.stdout.write(
                    f"{job['id']:<20} "
                    f"{job['name']:<20} "
                    f"{next_run:<20} "
                    f"{status:<10}"
                )
        
        self.stdout.write('=' * 80 + '\n')
    
    def _shutdown(self):
        """关闭调度器"""
        if self.scheduler_manager:
            self.stdout.write('正在关闭调度器...')
            self.scheduler_manager.stop_scheduler()
            self.stdout.write(
                self.style.SUCCESS('✅ 调度器已安全关闭')
            )
        
        self.stdout.write(
            self.style.SUCCESS('程序退出')
        )


# 导入 select 模块（用于非阻塞输入）
try:
    import select
except ImportError:
    # Windows 系统可能不支持 select
    import msvcrt
    
    def select_replacement(rlist, wlist, xlist, timeout):
        """Windows 下的 select 替代方案"""
        if msvcrt.kbhit():
            return (rlist, [], [])
        else:
            time.sleep(timeout)
            return ([], [], [])
    
    select.select = select_replacement